Nvidia Jetson NX 系列 01.使用 virtualenv 搭建 opencv-python 環境

這次專案是一個交通的 computer vision 案子,需要在 edge 端搭建 inference 模型要使用的環境。

Edge 端的機器是 Jetson Xavier NX,機台內部的初始環境是別人用好的 ubuntu 環境,支援 GPU;inference 的 python code 使用 tf.keras,所以環境需要有 tensorflow,另外也需要 opencv 的函式庫。

1
2
3
4
opencv-contrib-python
opencv-python
Keras
tensorflow-gpu

為了環境乾淨,原本就要把環境割離開來,不外乎的作法看能不能使用 conda 或 virtualenv,但 NX 是不支援安裝 anaconda 的,所以原先在遠端機器訓練模型用的環境不能直接移植過來。幫忙搭建 ubuntu 環境的人建議看要不要用用看 docker,所以在嘗試 virtualenv 之前,我是先用個 Dockerfile 建看看,果不其然 build image 時就遇到以下問題:

No matching distribution found for opencv-contrib-python

報錯位置在 Dockerfile pip install -r requirement.txt 安裝套件,就算不用 docker 也一樣 pip install 就會遇到這個報錯,然後應該是找不到 opencv-contrib,這時候我同事聽到表示也很有可能,畢竟 opencv 是 intel 開發的…… 好吧,大佬們這樣也挺合理啦 (摀臉)。

反正爬個文後,確實 opencv 是沒有提供模組給 ARM (參考連結),正好官方也給個解釋,要在人家產品上裝另一家的模組,那就乖乖從 source build 起來吧。

開工

綜合上述,碰壁後最後決定嘗試 python 提供的 virtualenv,沒有用過,但操作上可能和 conda 差不多吧? Docker 還要撰寫 Dockerfile,且 build resource 的過程感覺都還會遇到不可解的問題,所以 docker 方法我就果斷放棄了。

virtualenv 我自己看覺得這篇比較清楚,因為原本找的幾篇都沒有去設定 bashrc,並且似乎因為沒有導向 build 好的 resource,導致這一段當初我搭配虛擬環境再次出錯,過程不贅述;以結果來說就是 opencv 已經正在 make install 了,但 install 指向的環境錯了,package 跑到原生環境去,而且其實最後一段 make 沒有成功。

那就從頭來吧!首先先安裝相依套件:

1
2
3
4
5
# 更新套件
$ sudo apt-get update

# 安裝 OpenCV 相依套件
$ sudo apt-get install build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev

opencv source code & virtualenv

接下來我就從 Adrian Rosebrock 教學文的 step #2 開始參考。

1
2
3
4
5
6
7
8
9
10
11
# 下載 opencv 和 opencv_contrib,後面接要的版本號
$ wget -O opencv.zip https://github.com/opencv/opencv/archive/3.4.3.zip
$ wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/3.4.3.zip

# 解壓縮
$ unzip opencv_3.4.3.zip
$ unzip opencv_contrib_3.4.3.zip

# 改檔名
$ mv opencv_3.4.3.zip opencv
$ mv opencv_contrib_3.4.3.zip opencv_contrib

之前已經提過了需求,需要有 python 的 virtualenv 幫忙隔離環境。網路上其實會查到很多資源就直接使用 virtualenv,但我自己習慣使用 conda,看到 virtualenv 還需要切換到指定的虛擬環境資料夾才能 activate ,覺得有些麻煩,Andrian 的步驟三和上方關於虛擬環境的教學文裡的作法,都是利用 virtualenvwrapper 將整個工作流打包、統一管理虛擬環境並且修改環境變數。個人還是比較喜歡的。紀錄一下當時使用的命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ sudo pip install virtualenv virtualenvwrapper

## 開啟 ~/.bashrc 並下面這四行寫進去 ##
# virtualenv and virtualenvwrapper
export WORKON_HOME=$HOME/.virtualenvs
export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
source /usr/local/bin/virtualenvwrapper.sh
## 編輯結束 ##

$ source ~/.bashrc

# 我將虛擬環境命名為 det
$ mkvirtualenv det -p python3
$ workon det

$ pip install numpy

make opencv

接下來是 Andrian 教學裡面的步驟四。

1
2
3
4
5
6
7
8
9
10
11
12
# 要記得切換到當時改檔名的資料夾下
$ cd ~/opencv
$ mkdir build
$ cd build
$ cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CUDA_NVCC_FLAGS="-D_FORCE_INLINES –expt-relaxed-constexpr" \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D OPENCV_EXTRA_MODULES_PATH=~/efficientdet/opencv_contrib/modules \
-D OPENCV_ENABLE_NONFREE=ON \
-D PYTHON_EXECUTABLE=~/.virtualenvs/det/bin/python \
-D BUILD_EXAMPLES=ON ..

這裡主要是要搭建 openCV 的建置環境,要注意的是 cmake 參數要根據自己的情形進行調整。NX 是支援 GPU 計算的,所以 CUDA_NVCC_FLAGS 要進行設定,OPENCV_EXTRA_MODULES_PATH 就按照最後 opencv_contrib 的路徑位置設定、PYTHON_EXECUTABLE 要記得設置成虛擬環境 python 執行檔的位置。

有出現其他問題的人,也可翻一下 Andrian 教學文下方的討論區,看看有沒有類似的情形發生。


環境設置完成後,還需要 compile opencv,這裡要使用 make 指令。

1
$ make -j2

可查看自己的資源有幾個核心,後面的數字就改成支援的核心數量,像這裡支援的是 2 個。這邊 make 時間會很長,我等了大約 40-50 分鐘。完成後就可以安裝自己的 opencv。

套件連結至虛擬環境

接下來第五步,可能會出現一些分歧,主要是大家要找找自己 cv2.so 的檔案位置自哪裡,因為 opencv 版本的問題,我和教學文裡存放 .so 的位置不一樣,教學文的位置在 /usr/local/python/cv2/python-3.6。我的存放位置則是在 /usr/local/lib/python3.6/site-packages/

1
2
3
4
5
6
$ ls /usr/local/lib/python3.6/site-pakcages
cv2.cpython-36m-aarch64-linux-gnu.so

# 切換到剛剛找到 so 檔案的位置下,並改成簡單一點的檔名 cv2.so
$ cd /usr/local/lib/python3.6/site-pakcages
$ sudo mv cv2.cpython-36m-x86_64-linux-gnu.so cv2.so

最後要將檔案連結過去你的虛擬環境下。

1
2
$ cd ~/.virtualenvs/det/lib/python3.6/site-packages/
$ ln -s /usr/local/lib/python3.6/site-pakcages/cv2.so cv2.so

完成後可以在虛擬環境下測試看看 cv2 是否被成功裝起來。

1
2
3
4
5
6
7
8
9
10
$ cd ~
$ workon det
$ python
Python 3.6.9 (default, Jul 17 2020, 12:50:27)
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__
'3.4.3'
>>> quit()

大體上還算是順利吧,等 tensorflow-gpu 的套件也裝起來後,最終還是得看看 inference code 是否正常運行。


2020.08.18 補充

1
2
3
4
5
6
7
8
9
10
11
12
13
# 查看 RAM + SWAP 的容量
$ free -h
# 查看 SD 卡
$ df -h
# 查看 CPU 狀況
$ lscpu

# 查看 GPU 運行狀態
$ sudo /usr/bin/tegrastats
# 更改 power mode
$ sudo /usr/sbin/nvpmodel -m <x>
# 查看 power mode
$ sudo /usr/sbin/nvpmodel -q

可以用上述通用指令看一下 xavier 的狀況,要注意 xavier nx 有兩種 mode,低功率(10w)跟高功率(15w),兩種會使用的規格不一樣,10w 會啟動 2 個 CPU 或 4 個 CPU,15 w 則會全部啟動。

Nvidia 針對 jetson 家族的 power management 文件,請點


Reference

下一篇是 nvidia jetson nx 上搭建 tensorflow-gpu 環境。